#ifndef EFFECT_H_
#define EFFECT_H_

#include "object/animation.h"
#include <iostream>
#include <vector>
#include <map>

using namespace std;

/// EFFECT IDS ///
#define EFFECT_DIRECT_DAMAGE 			"effect_dd"
#define EFFECT_DAMAGE_OVER_TIME			"effect_dot"
#define EFFECT_ALIGNMENT_CHANGE			"effect_alignment_change"
//////////////////

/// EFFECT STATES ///
// the effect is loaded and ready to be used
#define EFFECT_STATE_LOADED					"loaded"
// the effect meets its prerequisites
#define EFFECT_STATE_READY					"ready"
// the effect is animating
#define EFFECT_STATE_ANIMATION_STARTED		"animation_started"
// the effect is done animating
#define EFFECT_STATE_ANIMATION_DONE			"animation_done"
// the effect is completely finished
#define EFFECT_STATE_FINISHED				"finished"
/////////////////////

/// EFFECT_ORIGINS ///
#define EFFECT_ORIGIN_PLAYER		0
//////////////////////

/// EFFECT_TARGETS ///
#define EFFECT_TARGET_ENEMY			"enemy"
//////////////////////

/// EFFECT_PREREQS ///
#define EFFECT_PREREQ_NONE			"none"
#define EFFECT_PREREQ_LOCAL			"local"
#define EFFECT_PREREQ_MIN_LEVEL		"min_level"
//////////////////////

/// EFFECT_ANIMATIONS ///
#define EFFECT_ANIMATION_NONE		"none"
#define EFFECT_ANIMATION_DEFAULT	"default"
#define EFFECT_ANIMATION_FIREBALL	"fireball"
#define EFFECT_ANIMATION_BURN		"burn"
/////////////////////////

/**
* An effect that a card could have on the playing field.
* 
* @author dfoelber
**/
class Effect
{
public:
	Effect(string id, string prereq, string alignment, double procRate, string shortText, string longText, string target, string animation, string trigger)
	{
		this->id = id;
		this->prereq = prereq;
		this->alignment = alignment;
		this->procRate = procRate;
		this->shortText = shortText;
		this->longText = longText;
		this->target = target;
		this->animation = animation;
		this->trigger = trigger;
		
		state = level = lifetime = origin = 0;
		useCastAnimation = true;
	}
	
	virtual ~Effect() {}
	
public:	
	string GetId() { return id; }
	void SetPrereq(string prereq) { this->prereq = prereq; }
	string GetPrereq() { return prereq; }
	string GetAlignment() { return alignment; }
	double GetProcRate() { return procRate; }
	string GetShortText() { return shortText; }
	string GetLongText() { return longText; }
	string GetTarget() { return target; }
	string GetAnimation() { return animation; }
	string GetTrigger() { return trigger; }
	
	virtual Effect* Copy()
	{
		Effect* effect = new Effect( id, prereq, alignment, procRate, shortText, longText, target, animation, trigger );
		effect->level = this->level;
		return effect;
	}
	
private:
	/// The ID of the effect.
	string 			id;
	/// The Prereqs of the effect.
	string 			prereq;
	/// The effect's alignment.
	string			alignment;
	/// The proc rate of the effect.
	double			procRate;
	/// The short text of the effect.
	string			shortText;
	/// The long, explanitory text of the effect.
	string			longText;
	/// Target information
	string			target;
	/// Animation ID
	string			animation;
	/// The trigger state
	string			trigger;
	
public: // internal information
	int					uid;
	int 				level;
	int					lifetime;
	string				state;
	int					origin;
	bool				useCastAnimation;
	map<string,string>	associations;
	AnimationObject*	animationObject;
};

/**
* A direct damage effect.
* 
* @author dfoelber
**/
class DirectDamageEffect : public Effect
{
public:
	DirectDamageEffect(vector<int> damage, string prereq, string alignment, double procRate, string shortText, string longText, string target, string animation, string trigger) :
		Effect(EFFECT_DIRECT_DAMAGE, prereq, alignment, procRate, shortText, longText, target, animation, trigger)
	{
		this->damage = damage;
	}
	
	vector<int> GetDamage() { return damage; }

	virtual Effect* Copy()
	{
		Effect* effect = new DirectDamageEffect( damage, GetPrereq(), GetAlignment(), GetProcRate(), GetShortText(), GetLongText(), GetTarget(), GetAnimation(), GetTrigger());
		effect->level = this->level;
		return effect;
	}
	
private:
	/// The damage value
	vector<int> 			damage;
};

/**
* An alignment change effect.
* 
* @author dfoelber
**/
class AlignmentChangeEffect : public Effect
{
public:
	AlignmentChangeEffect(vector<string> change, string prereq, string alignment, double procRate, string shortText, string longText, string target, string animation, string trigger) :
		Effect(EFFECT_ALIGNMENT_CHANGE, prereq, alignment, procRate, shortText, longText, target, animation, trigger)
	{
		this->change = change;
	}
	
	vector<string> GetChange() { return change; }

	virtual Effect* Copy()
	{
		Effect* effect = new AlignmentChangeEffect( change, GetPrereq(), GetAlignment(), GetProcRate(), GetShortText(), GetLongText(), GetTarget(), GetAnimation(), GetTrigger() );
		effect->level = this->level;
		return effect;
	}
	
private:
	/// The amount of change
	vector<string> 			change;
};

/**
* A damage over time effect.
* 
* @author dfoelber
**/
class DoTEffect : public Effect
{
public:
	struct DoT
	{
	public:
		int damage;
		int occur;
		int time;
	};
	
public:
	DoTEffect(vector<DoT> damage, string prereq, string alignment, double procRate, string shortText, string longText, string target, string animation, string trigger) :
		Effect(EFFECT_DAMAGE_OVER_TIME, prereq, alignment, procRate, shortText, longText, target, animation, trigger)
	{
		this->damage = damage;
		timeCounter = 0;
		tickCounter = 0;
	}
	
	vector<DoT> GetDamage() { return damage; }

	virtual Effect* Copy()
	{
		Effect* effect = new DoTEffect( damage, GetPrereq(), GetAlignment(), GetProcRate(), GetShortText(), GetLongText(), GetTarget(), GetAnimation(), GetTrigger() );
		effect->level = this->level;
		return effect;
	}
	
public:
	int						timeCounter;
	int						tickCounter;
	
private:
	/// The amount of damage
	vector<DoT> 			damage;
};
	
#endif /*EFFECT_H_*/
